<?php
namespace app\controller;

use app\BaseController;
use app\common\TokenAuth;
use think\facade\Db;
use think\facade\Request;

class MakeupApplication extends BaseController
{
    /**
     * 提交补卡申请
     */
    public function apply()
    {
        // 验证token并获取用户信息
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        // 获取请求参数
        $checkDate = Request::param('check_date/s', '');
        $checkType = Request::param('check_type/d', 0);
        $checkTime = Request::param('check_time/s', '');
        $reason = Request::param('reason/s', '');
        
        // 参数验证
        if (empty($checkDate) || empty($checkTime) || empty($reason)) {
            return json(['code' => 400, 'msg' => '参数不能为空']);
        }
        
        if (!in_array($checkType, [1, 2, 3, 4])) {
            return json(['code' => 400, 'msg' => '补卡类型参数错误']);
        }
        
        // 验证日期格式
        if (!strtotime($checkDate)) {
            return json(['code' => 400, 'msg' => '日期格式错误']);
        }
        
        // 验证时间格式
        if (!preg_match('/^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/', $checkTime)) {
            return json(['code' => 400, 'msg' => '时间格式错误']);
        }
        
        // 不能申请未来日期的补卡
        if ($checkDate > date('Y-m-d')) {
            return json(['code' => 400, 'msg' => '不能申请未来日期的补卡']);
        }
        
        // 不能申请超过30天前的补卡
        $thirtyDaysAgo = date('Y-m-d', strtotime('-30 days'));
        if ($checkDate < $thirtyDaysAgo) {
            return json(['code' => 400, 'msg' => '不能申请30天前的补卡']);
        }
        
        try {
            // 检查当月补卡次数限制
            $monthLimitCheck = $this->checkMonthlyMakeupLimit($user['id'], $checkDate);
            if ($monthLimitCheck['code'] !== 200) {
                return json($monthLimitCheck);
            }
            
            // 检查是否已有相同类型的补卡申请
            $existingApp = Db::name('makeup_application')
                ->where('user_id', $user['id'])
                ->where('check_date', $checkDate)
                ->where('check_type', $checkType)
                ->where('status', 'in', [1, 2]) // 待审核或已通过
                ->find();
                
            if ($existingApp) {
                return json(['code' => 400, 'msg' => '该时段已有补卡申请，请勿重复申请']);
            }
            
            // 检查该时段是否已经有打卡记录
            $record = Db::name('attendance_record')
                ->where('user_id', $user['id'])
                ->where('check_date', $checkDate)
                ->find();
            
            if ($record) {
                $hasRecord = $this->checkExistingPunch($record, $checkType);
                if ($hasRecord) {
                    return json(['code' => 400, 'msg' => '该时段已有打卡记录，无需补卡']);
                }
            }
            
            // 获取审批人（这里简化为获取部门负责人或管理员）
            $approverId = $this->getApprover($user['id']);
            if (!$approverId) {
                return json(['code' => 400, 'msg' => '未找到审批人，请联系管理员']);
            }
            
            // 创建补卡申请
            $applicationId = Db::name('makeup_application')->insertGetId([
                'user_id' => $user['id'],
                'check_date' => $checkDate,
                'check_type' => $checkType,
                'check_time' => $checkTime,
                'reason' => $reason,
                'status' => 1, // 待审核
                'approver_id' => $approverId,
                'create_time' => date('Y-m-d H:i:s')
            ]);
            
            return json([
                'code' => 200,
                'msg' => '补卡申请提交成功',
                'data' => ['application_id' => $applicationId]
            ]);
            
        } catch (\Exception $e) {
            trace('补卡申请失败: ' . $e->getMessage(), 'error');
            return json(['code' => 500, 'msg' => '申请失败：' . $e->getMessage()]);
        }
    }
    
    /**
     * 获取用户的补卡申请列表
     */
    public function getMyApplications()
    {
        // 验证token并获取用户信息
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        // 获取分页参数
        $page = Request::param('page/d', 1);
        $limit = Request::param('limit/d', 20);
        $status = Request::param('status/d'); // 可选的状态筛选
        
        // 构建查询
        $query = Db::name('makeup_application')
            ->alias('ma')
            ->join('user u', 'ma.approver_id = u.id', 'left')
            ->where('ma.user_id', $user['id']);
        
        // 状态筛选
        if (!is_null($status)) {
            $query = $query->where('ma.status', $status);
        }
        
        // 获取总记录数
        $total = $query->count();
        
        // 获取分页数据
        $list = $query
            ->field([
                'ma.id',
                'ma.check_date',
                'ma.check_type',
                'ma.check_time',
                'ma.reason',
                'ma.status',
                'ma.approve_time',
                'ma.approve_remark',
                'ma.create_time',
                'u.realname as approver_name'
            ])
            ->order('ma.create_time', 'desc')
            ->page($page, $limit)
            ->select();
        
        // 处理数据
        foreach ($list as &$item) {
            $item['check_type_text'] = $this->getCheckTypeText($item['check_type']);
            $item['status_text'] = $this->getStatusText($item['status']);
        }
        
        return json([
            'code' => 200,
            'msg' => '获取成功',
            'data' => [
                'total' => $total,
                'list' => $list
            ]
        ]);
    }
    
    /**
     * 获取待审批的补卡申请列表（管理员用）
     */
    public function getPendingApplications()
    {
        // 验证token并获取用户信息
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        // 获取请求参数（支持JSON格式）
        $input = Request::getContent();
        $params = json_decode($input, true) ?: [];
        
        $page = $params['pageNo'] ?? 1;
        $limit = $params['pageSize'] ?? 20;
        $status = $params['status'] ?? null;
        $keyword = $params['keyword'] ?? '';
        $startDate = $params['start_date'] ?? '';
        $endDate = $params['end_date'] ?? '';
        
        // 构建查询 - 管理员可以看到所有申请，普通用户只能看到自己需要审批的
        $query = Db::name('makeup_application')
            ->alias('ma')
            ->join('user u1', 'ma.user_id = u1.id')
            ->join('user u2', 'ma.approver_id = u2.id', 'left');
            
        // 如果不是管理员，只显示自己需要审批的申请
        if (!$user['is_leader']) {
            $query = $query->where('ma.approver_id', $user['id']);
        }
        
        // 状态筛选
        if (!is_null($status)) {
            if ($status === 'processed') {
                // 已审批：包含通过和拒绝
                $query = $query->where('ma.status', 'in', [2, 3]);
            } else {
                $query = $query->where('ma.status', $status);
            }
        }
        
        // 关键字搜索（按申请人姓名）
        if (!empty($keyword)) {
            $query = $query->where('u1.realname', 'like', "%{$keyword}%");
        }
        
        // 日期范围筛选
        if (!empty($startDate)) {
            $query = $query->where('ma.create_time', '>=', $startDate . ' 00:00:00');
        }
        if (!empty($endDate)) {
            $query = $query->where('ma.create_time', '<=', $endDate . ' 23:59:59');
        }
        
        // 获取总记录数
        $total = $query->count();
        
        // 如果是统计请求，返回统计数据
        if (isset($params['count_only']) && $params['count_only']) {
            // 获取待审批数量
            $pendingQuery = clone $query;
            $pendingCount = $pendingQuery->where('ma.status', 1)->count();
            
            // 获取已审批数量（通过和拒绝的总数）
            $processedQuery = clone $query;
            $processedCount = $processedQuery->where('ma.status', 'in', [2, 3])->count(); // 2=通过，3=拒绝
            
            return json([
                'code' => 200,
                'data' => [
                    'pending_count' => $pendingCount,
                    'processed_count' => $processedCount
                ]
            ]);
        }

        // 获取分页数据
        $list = $query
            ->field([
                'ma.id',
                'ma.check_date',
                'ma.check_type',
                'ma.check_time',
                'ma.reason',
                'ma.status',
                'ma.approve_time',
                'ma.approve_remark',
                'ma.create_time',
                'u1.realname as applicant_name',
                'u2.realname as approver_name'
            ])
            ->order('ma.create_time', 'desc')
            ->page($page, $limit)
            ->select();
        
        // 处理数据
        foreach ($list as &$item) {
            $item['check_type_text'] = $this->getCheckTypeText($item['check_type']);
            $item['status_text'] = $this->getStatusText($item['status']);
        }
        
        return json([
            'code' => 200,
            'msg' => '获取成功',
            'data' => [
                'total' => $total,
                'list' => $list
            ]
        ]);
    }
    
    /**
     * 审批补卡申请
     */
    public function approve()
    {
        // 验证token并获取用户信息
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        // 获取请求参数（支持JSON格式）
        $input = Request::getContent();
        $params = json_decode($input, true) ?: [];
        
        $id = $params['id'] ?? 0;
        $action = $params['status'] ?? 0; // 2通过 3拒绝
        $remark = $params['remark'] ?? '';
        
        // 参数验证
        if (empty($id) || !in_array($action, [2, 3])) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }
        
        // 查询补卡申请
        $query = Db::name('makeup_application')
            ->where('id', $id)
            ->where('status', 1); // 只能审批待审核的申请
            
        // 如果不是管理员，只能审批自己负责的申请
        if (!$user['is_leader']) {
            $query = $query->where('approver_id', $user['id']);
        }
        
        $application = $query->find();
            
        if (!$application) {
            return json(['code' => 400, 'msg' => '补卡申请不存在或已处理']);
        }
        
        try {
            Db::startTrans();
            
            // 更新补卡申请状态
            Db::name('makeup_application')
                ->where('id', $id)
                ->update([
                    'status' => $action,
                    'approve_time' => date('Y-m-d H:i:s'),
                    'approve_remark' => $remark
                ]);
            
            // 如果审批通过，更新考勤记录
            if ($action == 2) { // 补卡审批表中2表示审批通过
                $this->updateAttendanceForMakeup($application);
            }
            
            Db::commit();
            
            return json([
                'code' => 200,
                'msg' => $action == 2 ? '审批通过' : '审批拒绝'
            ]);
            
        } catch (\Exception $e) {
            Db::rollback();
            trace('补卡审批失败: ' . $e->getMessage(), 'error');
            return json(['code' => 500, 'msg' => '审批失败：' . $e->getMessage()]);
        }
    }
    
    /**
     * 撤销补卡申请
     */
    public function cancel()
    {
        // 验证token并获取用户信息
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        // 获取请求参数
        $id = Request::param('id/d');
        
        if (empty($id)) {
            return json(['code' => 400, 'msg' => '参数错误']);
        }
        
        // 查询补卡申请
        $application = Db::name('makeup_application')
            ->where('id', $id)
            ->where('user_id', $user['id'])
            ->where('status', 1) // 只能撤销待审核的申请
            ->find();
            
        if (!$application) {
            return json(['code' => 400, 'msg' => '补卡申请不存在或已处理，无法撤销']);
        }
        
        try {
            // 删除补卡申请
            Db::name('makeup_application')
                ->where('id', $id)
                ->delete();
            
            return json([
                'code' => 200,
                'msg' => '撤销成功'
            ]);
            
        } catch (\Exception $e) {
            trace('撤销补卡申请失败: ' . $e->getMessage(), 'error');
            return json(['code' => 500, 'msg' => '撤销失败：' . $e->getMessage()]);
        }
    }
    
    /**
     * 检查当月补卡次数限制
     */
    private function checkMonthlyMakeupLimit($userId, $checkDate)
    {
        // 获取考勤设置中的补卡次数限制
        $setting = Db::name('checkin_setting')
            ->where('status', 1)
            ->order('id', 'desc')
            ->find();
        
        if (!$setting || !isset($setting['makeup_limit'])) {
            return ['code' => 400, 'msg' => '未配置补卡次数限制'];
        }
        
        $makeupLimit = $setting['makeup_limit'];
        
        // 获取当月已通过的补卡次数
        $month = date('Y-m', strtotime($checkDate));
        $usedCount = Db::name('makeup_application')
            ->where('user_id', $userId)
            ->where('status', 2) // 已通过
            ->where('check_date', 'like', $month . '%')
            ->count();
        
        if ($usedCount >= $makeupLimit) {
            return ['code' => 400, 'msg' => "本月补卡次数已达上限（{$makeupLimit}次）"];
        }
        
        return ['code' => 200, 'msg' => '检查通过', 'used_count' => $usedCount, 'limit' => $makeupLimit];
    }
    
    /**
     * 检查已有打卡记录
     */
    private function checkExistingPunch($record, $checkType)
    {
        switch ($checkType) {
            case 1:
                return !empty($record['morning_check_in']);
            case 2:
                return !empty($record['morning_check_out']);
            case 3:
                return !empty($record['afternoon_check_in']);
            case 4:
                return !empty($record['afternoon_check_out']);
        }
        
        return false;
    }
    
    /**
     * 获取审批人
     */
    private function getApprover($userId)
    {
        // 简化逻辑：获取部门负责人作为审批人
        $userDept = Db::name('user_department_relation')
            ->where('user_id', $userId)
            ->find();
        
        if (!$userDept) {
            // 如果没有部门信息，返回管理员
            $admin = Db::name('user')
                ->where('is_leader', 1)
                ->where('status', 1)
                ->find();
            return $admin ? $admin['id'] : null;
        }
        
        // 查找部门负责人
        $leader = Db::name('user_department_relation')
            ->alias('udr')
            ->join('user u', 'udr.user_id = u.id')
            ->where('udr.department_id', $userDept['department_id'])
            ->where('u.is_leader', 1)
            ->where('u.status', 1)
            ->where('u.id', '<>', $userId) // 排除自己
            ->find();
        
        if ($leader) {
            return $leader['user_id'];
        }
        
        // 如果没有部门负责人，返回系统管理员
        $admin = Db::name('user')
            ->where('is_leader', 1)
            ->where('status', 1)
            ->find();
        
        return $admin ? $admin['id'] : null;
    }
    
    /**
     * 更新考勤记录（补卡通过后）
     */
    private function updateAttendanceForMakeup($application)
    {
        // 查询考勤记录
        $record = Db::name('attendance_record')
            ->where('user_id', $application['user_id'])
            ->where('check_date', $application['check_date'])
            ->find();
        
        $updateData = [];
        
        // 根据补卡类型更新对应时间和状态
        switch ($application['check_type']) {
            case 1: // 上午上班
                $updateData['morning_check_in'] = $application['check_time'];
                $updateData['morning_check_in_status'] = 5; // 补卡状态
                break;
            case 2: // 上午下班
                $updateData['morning_check_out'] = $application['check_time'];
                $updateData['morning_check_out_status'] = 5; // 补卡状态
                break;
            case 3: // 下午上班
                $updateData['afternoon_check_in'] = $application['check_time'];
                $updateData['afternoon_check_in_status'] = 5; // 补卡状态
                break;
            case 4: // 下午下班
                $updateData['afternoon_check_out'] = $application['check_time'];
                $updateData['afternoon_check_out_status'] = 5; // 补卡状态
                break;
        }
        
        $updateData['update_time'] = date('Y-m-d H:i:s');
        
        if ($record) {
            // 更新现有记录
            Db::name('attendance_record')
                ->where('id', $record['id'])
                ->update($updateData);
        } else {
            // 创建新记录
            $updateData['user_id'] = $application['user_id'];
            $updateData['check_date'] = $application['check_date'];
            $updateData['remark'] = '补卡生成';
            $updateData['create_time'] = date('Y-m-d H:i:s');
            
            // 获取考勤设置确定工作类型，如果表不存在则使用默认值
            try {
                $setting = Db::name('attendance_settings')->where('id', 1)->find();
                $workType = $setting['work_type'] ?? 2;
            } catch (\Exception $e) {
                // 如果表不存在，使用默认工作类型
                $workType = 2; // 默认两次上下班
            }
            $updateData['work_type'] = $workType;
            
            // 初始化其他状态字段为缺卡
            if ($application['check_type'] != 1) {
                $updateData['morning_check_in_status'] = 3; // 缺卡
            }
            if ($application['check_type'] != 2 && $workType >= 1) {
                $updateData['morning_check_out_status'] = 3; // 缺卡
            }
            if ($application['check_type'] != 3 && $workType == 2) {
                $updateData['afternoon_check_in_status'] = 3; // 缺卡
            }
            if ($application['check_type'] != 4 && $workType == 2) {
                $updateData['afternoon_check_out_status'] = 3; // 缺卡
            }
            
            Db::name('attendance_record')->insert($updateData);
        }
    }
    
    /**
     * 获取打卡类型文本
     */
    private function getCheckTypeText($checkType)
    {
        $types = [
            1 => '上午上班',
            2 => '上午下班',
            3 => '下午上班',
            4 => '下午下班'
        ];
        
        return $types[$checkType] ?? '未知';
    }
    
    /**
     * 获取状态文本
     */
    private function getStatusText($status)
    {
        $statuses = [
            1 => '待审核',
            2 => '已通过',
            3 => '已拒绝'
        ];
        
        return $statuses[$status] ?? '未知';
    }
}